package com.itheima.servcie;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.itheima.bean.CodeBean;
import com.itheima.dbservice.QuestionServiceApi;
import com.itheima.dbservice.UserInfoServiceApi;
import com.itheima.dbservice.UserService;
import com.itheima.exception.CommonException;
import com.itheima.mongoservice.*;
import com.itheima.pojo.Question;
import com.itheima.pojo.ReplyVo;
import com.itheima.pojo.User;
import com.itheima.pojo.UserInfo;
import com.itheima.pojo.mongo.*;
import com.itheima.template.HuanXinTemplate;
import com.itheima.vo.PersonalInfoVo;
import com.itheima.vo.TodayBestVo;
import com.itheima.vo.mongo.AllVo;
import com.itheima.vo.mongo.NearUserVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.Code;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class TanhuaService {
    @DubboReference
    private UserInfoServiceApi userInfoServiceApi;
    @DubboReference
    private TanhuaServiceApi tanhuaServiceApi;
    @DubboReference
    private QuestionServiceApi questionServiceApi;
    @DubboReference
    private UserService userService;
    @DubboReference
    private UserLikeServiceApi userLikeServiceApi;
    @DubboReference
    private FriendServiceApi friendServiceApi;
    @DubboReference
    private UserLocationServiceApi userLocationServiceApi;
    @DubboReference
    private VisitorsServiceApi visitorsServiceApi;
    @Autowired
    private MessagesService messagesService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private HuanXinTemplate huanXinTemplate;


    public TodayBestVo todayBest() {
        log.info("当前线程:{}", Thread.currentThread().getName());
        //当前用户uid
//        Long uid = BaseContext.getThreadLocalId();
        String uid = redisTemplate.opsForValue().get(CodeBean.ID);
        log.info(uid);

        RecommendUser recommendUser = tanhuaServiceApi.getTodayBest(Convert.toLong(uid));
        if (ObjectUtil.isNull(recommendUser)){
            //给个随机佳人用户
            UserInfo userInfo = userInfoServiceApi.getUserInfoById(1L);
            log.info("得到的佳人信息：{}", userInfo);

            //复制到vo
            TodayBestVo todayBestVo = new TodayBestVo();
            //标签再做封装
            BeanUtil.copyProperties(userInfo, todayBestVo, "tags");
            String[] tags = userInfo.getTags().split(",");
            todayBestVo.setTags(tags);
            //封装缘分值
            todayBestVo.setFateValue(Convert.toInt(recommendUser.getScore()));

            return todayBestVo;
        }
        Long jid = recommendUser.getUserId();
        UserInfo userInfo = userInfoServiceApi.getUserInfoById(jid);
        log.info("得到的佳人信息：{}", userInfo);

        //复制到vo
        TodayBestVo todayBestVo = new TodayBestVo();
        //标签再做封装
        BeanUtil.copyProperties(userInfo, todayBestVo, "tags");
        String[] tags = userInfo.getTags().split(",");
        todayBestVo.setTags(tags);
        //封装缘分值
        todayBestVo.setFateValue(Convert.toInt(recommendUser.getScore()));

        return todayBestVo;
    }

    public AllVo recommendation(Integer page, Integer pagesize) {
        Long id = Convert.toLong(redisTemplate.opsForValue().get(CodeBean.ID));
        List<RecommendUser> list = tanhuaServiceApi.recommendationByPage(page, pagesize, id);

        //封装所有推荐佳人信息
        List<PersonalInfoVo> personalInfoVoList = new ArrayList<>();
        for (RecommendUser recommendUser : list) {
            Long userId = recommendUser.getUserId();
            UserInfo userInfo = userInfoServiceApi.getUserInfoById(userId);
            //复制返回数据到vo
            PersonalInfoVo personalInfoVo = new PersonalInfoVo();
            BeanUtil.copyProperties(userInfo, personalInfoVo, "tags");
            String[] tags = userInfo.getTags().split(",");
            personalInfoVo.setTags(tags);
            //封装缘分值
            personalInfoVo.setFateValue(Convert.toInt(recommendUser.getScore()));
            //将封装好的结果添加集合
            personalInfoVoList.add(personalInfoVo);
        }
        AllVo allVo = new AllVo();
        allVo.setItems(list.toArray());
        allVo.setPage(page);
        allVo.setPagesize(pagesize);
        allVo.setItems(personalInfoVoList.toArray());
        //返回封装数据
        return allVo;
    }

    public String strangerQuestions(String userId) {
        Question question = questionServiceApi.getQuestionInfo(userId);
        if (ObjectUtil.isNull(question)){
            question = new Question();
            question.setTxt("你喜欢java吗，如果不喜欢，那么我并不是很认可");
        }
        return question.getTxt();
    }

    public void replyQuestions(Map map) {
        Long userId = Convert.toLong(map.get("userId"));//接收方id
        String reply = Convert.toStr(map.get("reply"));//回答
        //获取当前用户信息封装发送信息
        Long uid = Convert.toLong(redisTemplate.opsForValue().get(CodeBean.ID));
        User user = userService.getUser(Convert.toStr(uid));
        UserInfo userInfo = userInfoServiceApi.getUserInfoById(uid);
        Question question = questionServiceApi.getQuestionInfo(Convert.toStr(userId));
        //封装
        ReplyVo replyVo = new ReplyVo();
        replyVo.setUserId(uid);
        replyVo.setNickname(userInfo.getNickname());
        replyVo.setHuanXinId(user.getHxUser());
        replyVo.setReply(reply);
        replyVo.setStrangerQuestion(ObjectUtil.isNull(question) ? "你喜欢java吗，如果不喜欢，那么我并不是很认可" : question.getTxt());
        //发送
        String jsonStr = JSONUtil.toJsonStr(replyVo);
        Boolean aBoolean = huanXinTemplate.sendMsg(CodeBean.HX_USER_PREFIX + userId, jsonStr);
        if (!aBoolean){
            throw new CommonException("发送失败");
        }
    }

    public PersonalInfoVo personalInfo(Long id) {
        UserInfo userInfo = userInfoServiceApi.getUserInfoById(id);
        //将登录者信息存入visitor集合中
        saveVisitor(id);
        //复制返回数据到vo
        PersonalInfoVo personalInfoVo = new PersonalInfoVo();
        BeanUtil.copyProperties(userInfo, personalInfoVo, "tags");
        String[] tags = userInfo.getTags().split(",");
        personalInfoVo.setTags(tags);
        //获取当前用户id
        Long uid = Convert.toLong(redisTemplate.opsForValue().get(CodeBean.ID));
        RecommendUser recommendUser = tanhuaServiceApi.getRecommendationUser(id, uid);
        //封装缘分值
        personalInfoVo.setFateValue(ObjectUtil.isNull(recommendUser) ? 50 : Convert.toInt(recommendUser.getScore()));

        return personalInfoVo;
    }

    private void saveVisitor(Long id) {
        //获取登录者id
        Long uid = Convert.toLong(redisTemplate.opsForValue().get(CodeBean.ID));
        //查看个人信息应被排除
        if (ObjectUtil.equal(id, uid)){
            return;
        }
        //访客信息是否存在
        Visitors visitorInfo = visitorsServiceApi.getVisitorInfo(uid, id);
        //获取登录用户对访问用户的缘分值
        RecommendUser recommendationUser = tanhuaServiceApi.getRecommendationUser(uid, id);
        //封装信息
        Visitors visitors = new Visitors();
        //对id进行判断
        if (ObjectUtil.isNotNull(visitorInfo)){
            visitors.setId(visitorInfo.getId());
        }
//        visitors.setId(ObjectUtil.isNull(visitorInfo) ? null : visitorInfo.getId());
        visitors.setUserId(id);
        visitors.setVisitorUserId(uid);
        visitors.setDate(System.currentTimeMillis());
        visitors.setFrom("首页");
        visitors.setScore(ObjectUtil.isNull(recommendationUser) ? 59.9 : recommendationUser.getScore());
        visitors.setVisitDate(new SimpleDateFormat("yyyyMMdd").format(new Date()));
        //有则更新集合，无则存入集合
        visitorsServiceApi.save(visitors);
    }

    public List<PersonalInfoVo> cards() {
        //TODO:取出异性信息（待优化）
        List<UserInfo> userInfoList = userInfoServiceApi.getAllUser();
        //排除已喜欢或不喜欢的（还有自己的id）
        Long uid = Convert.toLong(redisTemplate.opsForValue().get(CodeBean.ID));
        List<UserLike> userLikeList = userLikeServiceApi.getUserInfos(uid);

        List<PersonalInfoVo> list = new ArrayList<>();
        lo:
        for (UserInfo userInfo : userInfoList) {
            for (UserLike userLike : userLikeList) {
                if (ObjectUtil.equal(userInfo.getId(), userLike.getLikeUserId())){
                    continue lo;
                }
            }
            //判断自己id
            if (ObjectUtil.equal(userInfo.getId(), uid)){
                continue;
            }
            //封装
            PersonalInfoVo personalInfoVo = new PersonalInfoVo();
            BeanUtil.copyProperties(userInfo, personalInfoVo, "tags");
            String[] tags = userInfo.getTags().split(",");
            personalInfoVo.setTags(tags);
            list.add(personalInfoVo);
        }
        return list;
    }

    public void love(Long id) {
        //获取登录用户id
        Long uid = Convert.toLong(redisTemplate.opsForValue().get(CodeBean.ID));
        //判断不喜欢是否存在
        boolean likeExist = userLikeServiceApi.getIsLikeExist(uid, id, false);
        if (likeExist){
            //改为喜欢
            userLikeServiceApi.updateIsLike(uid, id, true);
        }else {
            //查询喜欢是否存在
            boolean res = userLikeServiceApi.getIsLikeExist(uid, id, true);
            if (res){
                addLikeFriend(id, uid);
                return;
            }
            UserLike userLike = new UserLike();
            userLike.setLike(true);
            userLike.setLikeUserId(id);
            userLike.setUserId(uid);
            userLike.setCreated(System.currentTimeMillis());
            userLike.setUpdated(System.currentTimeMillis());
            userLikeServiceApi.addLikeInfo(userLike);
        }
        //判断并添加好友
        addLikeFriend(id, uid);
    }

    private void addLikeFriend(Long id, Long uid) {
        //查询对方是否也喜欢我
        boolean isLikeExist = userLikeServiceApi.getIsLikeExist(id, uid, true);
        if (isLikeExist){
            //查询好友列表是否存在
            boolean friendExist = friendServiceApi.isFriendExist(uid, id);
            boolean friendExist1 = friendServiceApi.isFriendExist(id, uid);
            if (!friendExist && !friendExist1){
                //添加好友
                messagesService.addFriend(Convert.toInt(id));
            }
        }
    }

    public void unlove(Long id) {
        //获取登录用户id
        Long uid = Convert.toLong(redisTemplate.opsForValue().get(CodeBean.ID));
        //查询喜欢是否存在
        boolean likeExist = userLikeServiceApi.getIsLikeExist(uid, id, true);
        if (likeExist){
            //更改isLike为false
            userLikeServiceApi.updateIsLike(uid, id, false);
        }else {
            //查询不喜欢是否存在
            boolean res = userLikeServiceApi.getIsLikeExist(uid, id, false);
            if (!res){
                UserLike userLike = new UserLike();
                userLike.setLike(false);
                userLike.setLikeUserId(id);
                userLike.setUserId(uid);
                userLike.setCreated(System.currentTimeMillis());
                userLike.setUpdated(System.currentTimeMillis());
                userLikeServiceApi.addLikeInfo(userLike);
            }
        }
        //删除好友关系
        friendServiceApi.deleteFriend(uid, id);
    }

    public List<NearUserVo> search(String gender, Integer distance) {
        //获取当前登录者id
        Long uid = Convert.toLong(redisTemplate.opsForValue().get(CodeBean.ID));
        //获取用户附近的其他探花用户
        List<Long> userIds = userLocationServiceApi.getSearchUser(uid, distance);
        //查询用户信息
        List<NearUserVo> list = new ArrayList<>();
        for (Long userId : userIds) {
            UserInfo userInfo = userInfoServiceApi.getUserInfoById(userId);
            //封装
            if (!ObjectUtil.equal(userInfo.getGender(), gender))
                continue;
            if (ObjectUtil.equal(userInfo.getId(), uid))
                continue;
            list.add(NearUserVo.init(userInfo));
        }
        return list;
    }
}
